package org.yh.demo.algorithm;

import org.junit.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;

public class ThreadTakeTurns {

    private final static int NUM = 1000;

    /**
     * 采用wait和notify交替打印
     */
    @Test
    public void test1(){

        Object o = new Object();
        CountDownLatch cd = new CountDownLatch(1);

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    cd.await();
                    synchronized (o) {
                        for (int i = 0; i < NUM; i++) {
//                        synchronized (o) {
                            System.out.print("1");
                            o.notify();
                            o.wait();
//                        }
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (o) {
                        cd.countDown();
                        for (int i = 0; i < NUM; i++) {
                            /**
                             * 同步不能放在循环内部，原因在于每次退出同步块后会释放锁导致两个线程重新公平竞争
                             * 竞争的情况下又可能被线程1竞争去执行了notify，导致2线程还未处于wait状态
                             */
//                        synchronized (o) {
//                            if(i==0){
//                                cd.countDown();
//                            }
                            o.wait();
                            System.out.print("2");
                            o.notify();
//                        }
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        long a = System.currentTimeMillis();
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\n"+(System.currentTimeMillis()-a));
    }

    /**
     * 采用Semaphore交替打印
     */
    @Test
    public void test2(){

        Semaphore s1 = new Semaphore(1);
        Semaphore s2 = new Semaphore(0);

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i < NUM; i++) {
                        s1.acquire();
                        System.out.print("1");
                        s2.release();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i < NUM; i++) {
                        s2.acquire();
                        System.out.print("2");
                        s1.release();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        long a = System.currentTimeMillis();
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\n"+(System.currentTimeMillis()-a));
    }
}
